package com.zbkj.service.monitor;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import com.zbkj.common.exception.AppException;
import com.zbkj.common.model.monitor.ZfbMonitorEquipment;
import com.zbkj.common.monitorchannel.GetDeviceModelV3Request;
import com.zbkj.common.monitorchannel.GetMultiMediaAddrV3Request;
import com.zbkj.common.monitorchannel.GetMultiMediaAddrV3Response;
import com.zbkj.common.monitorchannel.GetMultiMediaRecordV3Request;
import com.zbkj.common.monitorchannel.vo.*;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * @ClassName: MonitorChannelMain
 * @Description: TODO
 * @Author: fanbing
 * @Date: 2024/6/29 18:15
 * @Version: V1.0
 **/
@Component
public class MonitorChannelHandle implements ApplicationContextAware {


    private Map<Integer, IMonitorChannel> monitorChannelMap;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        Map<String, IMonitorChannel> beanMap = applicationContext.getBeansOfType(IMonitorChannel.class);
        Collection<IMonitorChannel> values = beanMap.values();
        if (CollectionUtil.isEmpty(values)) {
            return;
        }
        monitorChannelMap = values.stream().collect(Collectors.toMap(o -> o.getChannel().getType(), v -> v, (r, j) -> r));
    }


    /**
     * 校验是否存在该渠道
     *
     * @param MonitorChannelType
     * @return
     */
    private IMonitorChannel checkMonitorChannel(Integer MonitorChannelType) {
        IMonitorChannel iMonitorChannel = monitorChannelMap.get(MonitorChannelType);
        if (ObjectUtil.isNull(iMonitorChannel)) {
            throw new AppException("未配置渠道商");
        }
        return iMonitorChannel;
    }


    /**
     * 查询流媒体地址
     *
     * @param license
     * @param MonitorChannelType 见枚举MonitorChannelEnums
     */
    public MonitorChannelMediaAddressVo getMediaAddress(String license, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getMediaAddress(license);
    }


    /**
     * 唤醒设备
     *
     * @param license
     */
    public boolean wakeUpEquipment(String license, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.wakeUpEquipment(license);
    }


    /**
     * 获取设备状态
     *
     * @param license
     * @return
     */
    public MonitorChannelEquipmentStatusVo getEquipmentStatus(String license, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);

        return iMonitorChannel.getEquipmentStatus(license);
    }


    /**
     * ptz控制
     *
     * @param ctrlPTZRequestVo
     * @return
     */
    public boolean ctrlPTZ(CtrlPTZRequestVo ctrlPTZRequestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.ctrlPTZ(ctrlPTZRequestVo);
    }


    /**
     * 通过该命令向设备设置时间信息
     *
     * @param setTimeRequestVo
     * @param MonitorChannelType
     * @return
     */
    public boolean setTime(MonitorSetTimeRequestVo setTimeRequestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.setTime(setTimeRequestVo);
    }


    /**
     * 通知设备进⾏行行物理理变焦
     * 鹤梦云-2.6.2.8.6 通知设备进⾏行行物理理变焦
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo setAdjustFocalLength(AdjustFocalLengthRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.setAdjustFocalLength(requestVo);
    }


    /**
     * 通知设备抓图
     * 鹤梦云-4.6.2.2.8 通知设备抓图
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo noticeDeviceUploadPicRequest(NoticeDeviceUploadPicRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.noticeDeviceUploadPicRequest(requestVo);
    }


    /**
     * 查询设备云端录像⽇日历
     * 4.6.2.3.1 查询设备云端录像⽇日历
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<VideoQueryCalendarResultVo> getVideoQueryCalendar(VideoQueryCalendarRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getVideoQueryCalendar(requestVo);
    }


    /**
     * 查询设备云端录像列列表
     * 4.6.2.3.2 查询设备云端录像列列表
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<VideoQueryListResultVo> getVideoQueryList(VideoQueryListRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getVideoQueryList(requestVo);
    }

    /**
     * 查询设备云端录像详情
     * 4.6.2.3.3 查询设备云端录像详情
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<VideoQueryDetailResultVo> getVideoQueryDetail(VideoQueryDetailRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getVideoQueryDetail(requestVo);
    }

    /**
     * 查询设备云端图⽚片列列表
     * 4.6.2.2.2 查询设备云端图⽚片列列表
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<PictureQueryListResultVo> getPictureQueryList(VideoQueryListRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getPictureQueryList(requestVo);
    }


    /**
     * 查询设备云端图⽚片详情
     * 4.6.2.2.3 查询设备云端图⽚片详情
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<PictureQueryDetailResultVo> getPictureQueryDetail(PictureQueryDetailRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getPictureQueryDetail(requestVo);
    }

    /**
     * 查询设备云端图⽚片详情
     * 鹤梦云-4.6.2.2.7 查询设备本地图⽚片列列表(须设备在线才可查询)
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<GetLocalPicListResultVo> getGetLocalPicList(VideoQueryListRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getGetLocalPicList(requestVo);
    }

    /**
     * 查询设备本地录像列列表
     * 鹤梦云-4.6.2.3.5 查询设备本地录像列列表
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo<GetLocalFileListResultVo> getLocalFileList(GetLocalFileListRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.getLocalFileList(requestVo);
    }


    /**
     * 鹤梦云-4.6.2.2.5 根据事件时间查询设备云端图⽚片详情
     */
    public ThirdMonitorResultVo<PictureQueryDetailByTimeResultVo> QueryDetailByTime(QueryDetailByTimeRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.QueryDetailByTime(requestVo);
    }


    /**
     * 4.5.1 根据产品ID进⾏行行订阅数据
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo subscribe(MonitorSubscribeRequestVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.subscribe(requestVo);
    }

    /**
     * 4.6.2.6.3 摄像头开关
     *
     * @param requestVo
     * @return
     */
    public ThirdMonitorResultVo setOpenFlag(MonitorSetOpenFlagVo requestVo, Integer MonitorChannelType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(MonitorChannelType);
        return iMonitorChannel.setOpenFlag(requestVo);
    }

    /**
     * 4.6.2.3.4 查询设备本地录像⽇日历
     *
     * @param requestVo
     * @param equipmentType
     * @return
     */
    public ThirdMonitorResultVo getLocalFileCalendar(GetLocalFileCalendarVo requestVo, Integer equipmentType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.getLocalFileCalendar(requestVo);
    }

    /**
     * 获取v3版本的 accessToken
     *
     * @return
     */
    public String getV3AccessToken(Integer equipmentType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.getV3AccessToken();
    }

    /**
     * 5.5.8.2 获取 TF 录像回放地址标准流地址
     * 功能说明：
     * 1、获取设备流媒体录像回放地址；
     * 2、请求路径 url: /GMModule/V3/Media/GetMultiMediaRecordAddr；
     *
     * @param requestVo
     * @return
     */
    public GetMultiMediaRecordAddrV3Response GetMultiMediaRecordAddr(GetMultiMediaRecordAddrV3Request requestVo, Integer equipmentType) {

        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.GetMultiMediaRecordAddr(requestVo);
    }


    /**
     * 5.5.3.2 查询 TF 卡录像列表
     * 功能说明：
     * 1、按照日期查询 TF 卡录像列表；
     * 2、请求 URL；/GMModule/V3/Device/GetLocalFileList；
     *
     * @param requestVo
     * @return
     */
    public GetLocalFileListV3Response GetLocalFileList(GetLocalFileListV3Request requestVo, Integer equipmentType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.GetLocalFileList(requestVo);

    }


    /**
     * 5.5.3.3 查询 TF 卡事件日历
     * 功能说明：
     * 1、查询 TF 卡那天存在报警事件；
     * 2、请求 URL；/GMModule/V3/Device/GetLocalEventCalendar
     *
     * @param requestVo
     * @return
     */
    public GetLocalEventCalendarV3Response GetLocalEventCalendar(GetLocalEventCalendarV3Request requestVo, Integer equipmentType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.GetLocalEventCalendar(requestVo);
    }


    /**
     * 5.2.2 用户账号添加/删除设备
     * 功能说明：
     * 1、用户添加或者删除设备；
     * 2、该接口影响用户对设备的所有操作;
     * 3、请求路径 url: /GMModule/SetDevices;
     *
     * @param requestVo
     * @return
     */
    public SetDevicesV3Response SetDevices(SetDevicesV3Request requestVo, Integer equipmentType) {
        //获取监控渠道
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.SetDevices(requestVo);

    }


    /**
     * 5.5.1.1 查询设备的业务配置
     * 功能说明：
     * 1、根据功能模块类型查询设备的配置和能力；
     * 2、请求 URL；/GMModule/V3/Device/GetDeviceModel;
     *
     * @param requestVo
     * @return
     */
    public JSONObject GetDeviceModel(GetDeviceModelV3Request requestVo, Integer equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.GetDeviceModel(requestVo);

    }

    /**
     * 5.5.8.1 获取直播播放地址
     * 功能说明：
     * 1、获取设备流媒体直播地址；
     * 2、请求路径 url: /GMModule/V3/Media/GetMultiMediaAddr；
     *
     * @param requestVo
     * @return
     */
    public GetMultiMediaAddrV3Response GetMultiMediaAddr(GetMultiMediaAddrV3Request requestVo, Integer equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.GetMultiMediaAddr(requestVo);
    }

    /**
     * 5.5.8.2获取TF录像回放地址标准流地址
     * 1、获取设备流媒体录像回放地址；
     * 2、请求路径url:/GMModule/V3/Media/GetMultiMediaRecordAddr；
     *
     * @param request
     * @return
     */
    public GetMultiMediaAddrV3Response GetMultiMediaRecordV3Request(GetMultiMediaRecordV3Request request, Integer equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.GetMultiMediaRecordV3Request(request);
    }

    /**
     * 5.5.4.7 摄像机开关
     * 功能说明：
     * 1、关闭摄像机后，停止所有录制，同时app默认不可以观看，同时镜头转向隐私位；
     * 2、请求URL；/GMModule/V3/Device/SetOpenFlag
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3SetOpenFlag(MonitorSetOpenFlagVo requestVo, Integer equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3SetOpenFlag(requestVo);
    }
    /**
     * 5.5.4.2 重启设备
     * 功能说明：
     * 1、重启设备；
     * 2、请求URL；/GMModule/V3/Device/RebootDevice
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3RebootDevice(MonitorRebootDeviceVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3RebootDevice(requestVo);
    }


    /**
     * 5.5.4.3 检测设备版本是否可升级
     * 功能说明：
     * 1、后台比较设备当前版本号与后台版本号，当后台版本呢大于当前版本，则可升级；
     * 比较方式：strcmp("当前版本号","后台版本号") > 0 ；
     * 2、请求 URL；；/GMModule/V3/Device/CheckDeviceUpgradeVersion
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3CheckDeviceUpgradeVersion(MonitorBaseVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3CheckDeviceUpgradeVersion(requestVo);
    }


    /**
     * 5.5.4.4 通知设备升级到最新版本
     * 功能说明：
     * 1、当检测设备有新版后，通知设备进行 OTA；
     * 2、请求 URL；/GMModule/V3/Device/NoticeUpgradeDeviceToLatestVersion
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3NoticeUpgradeDeviceToLatestVersion(MonitorBaseVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3NoticeUpgradeDeviceToLatestVersion(requestVo);
    }


    /**
     * 5.5.4.17 获取 TF 卡信息
     * 功能说明：
     * 1、查询 TF 卡的容量信息；
     * 2、请求 URL；/GMModule/V3/Device/GetSDCardInfo
     *
     * @param requestVo
     * @returnF
     */
    public MonitorGetSDCardInfoResultVo v3GetSDCardInfo(MonitorBaseVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3GetSDCardInfo(requestVo);
    }
    /**
     * 5.5.4.18 格式化 TF 卡
     * 功能说明：
     * 1、格式话设备 TF 卡，TF 卡数据将会全部丢失；
     * 2、请求 URL；/GMModule/V3/Device/FormatSDCard
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3FormatSDCard(MonitorBaseVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3FormatSDCard(requestVo);
    }

    /**
     * 5.5.4.19 设置设备名称
     * 功能说明：
     * 1、修改设备的名称；
     * 2、请求 URL；/GMModule/V3/Device/SetDeviceName
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3SetDeviceName(MonitorSetDeviceNameVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3SetDeviceName(requestVo);
    }
    /**
     * 5.5.4.26 控制设备进行放大和缩小
     * 功能说明：
     * 1、当设备具有变焦能力的时候，通过该接口通知设备变焦，可以是电子变焦或光学变
     * 焦；
     * 2、请求 URL；/GMModule/V3/Device/AdjustFocalLength
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3AdjustFocalLength(MonitorAdjustFocalLengthVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3AdjustFocalLength(requestVo);
    }


    /**
     * 5.5.4.27 设置电池工作模式
     * 功能说明：
     * 1、设置电池摄像机的工作模式，前提是设备支持工作模式切换；
     * 2、请求 URL；/GMModule/V3/Device/SetBatteryWorkMode
     *
     * @param requestVo
     * @return
     */
    public JSONObject v3SetBatteryWorkMode(MonitorSetBatteryWorkModeVo requestVo, int equipmentType) {
        IMonitorChannel iMonitorChannel = this.checkMonitorChannel(equipmentType);
        return iMonitorChannel.v3SetBatteryWorkMode(requestVo);
    }

}
